package com.etone.smartAudit.service;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.etone.eos.domain.*;
import com.etone.eos.handler.SmartEosHandler;
import com.github.pagehelper.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.security.MessageDigest;

/***
 * eos区块链调用
 */
@Slf4j
@Service
public class EosService {
    /***
     * 账户名称
     */
    @Value("${eos.account:jjyy}")
    private String account;
    /***
     * 合约名称
     */
    @Value("${eos.code:jjyy}")
    private String code;
    /***
     * 合约表名称
     */
    @Value("${eos.md5TableName:cmitfilemd5s}")
    private String md5TableName;

    /**
     * chain地址
     */
    @Value("${eos.urlChain:http://192.168.174.128:8888}")
    private String urlChain;

    /***
     *签名私钥
     */
    @Value("${eos.privateKey:5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3}")
    private String privateKey;

    private SmartEosHandler eosHandler;

    public EosService() {

    }

    public SmartEosHandler getHander() {
        if (eosHandler == null) {
            EosConfig config = EosConfig.builder()
                    .account(account)
                    .code(code)
                    .account(account)
                    .md5TableName(md5TableName)
                    .url_chain(urlChain)
                    .privateKey(privateKey)
                    .build();
            return new SmartEosHandler(config);
        }
        return eosHandler;
    }


    /***
     * 添加数据到区块链
     * @param dto  文件md5值
     * @param
     * @return
     */
    public MD5FileVO addFile(CreateParamDTO dto) {
        CreateParam createParam = new CreateParam();
        createParam.setId(System.currentTimeMillis());
        createParam.setMd5(dto.getMd5());
        createParam.setUserId(dto.getUserId());
        createParam.setAppId(dto.getAppId());
        createParam.setFile_name(dto.getFileName());
        CreateParamVO result = getHander().addFileToAction(createParam);

        MD5FileVO md5FileVO = new MD5FileVO();
        md5FileVO.setFile_name(result.getFile_name());
        md5FileVO.setHash(result.getSha256_id());
        md5FileVO.setMd5(result.getMd5());
        md5FileVO.setTm(result.getTm());
        md5FileVO.setId(result.getId());
        return md5FileVO;
    }

    /***
     * 根据md5获取合约数据
     * @param md5
     * @return
     */
    public MD5FileVO getFileBymd5(String md5) {
        String actionId = String.valueOf(ConvertNum(md5));
        MD5FileVO fileVO = getHander().getTable(actionId);
        if (fileVO == null) {
            log.error("获取不到区块链数据");
        }
        return fileVO;
    }

    /***
     * 获取交易记录需要开启 eosio::history_api_plugin插件
     * filter-on = jjyy:create:  或者 filter-on = *
     * @param trxId
     * @return
     */
    public TransactionDetail getTransactionDetail(String trxId) {
//        TransactionDetail.TracesBean.ActBean.DataBeanX dataBeanX = transactionDetail.getTraces().get(0).getAct().getData();
        return getHander().getTransactionDetail(trxId);
    }

    /***
     * 获取存储在区块链中的数据
     * @param actionId
     * @return
     */
    public MD5FileVO getFile(String actionId) {
        MD5FileVO fileVO = getHander().getTable(actionId);
        if (fileVO == null) {
            log.error("获取不到区块链数据");
        }
        return fileVO;
    }

    /**
     * md5转数值型
     * 这个算法返回值理想长度是16，因为md.length = 16
     */
    public static String ConvertNum(String s) {
        if (StringUtil.isEmpty(s)) {
            return null;
        }
        // 这里根据MD5时间的值更换16进制abc的大小写
        char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
        try {
            byte[] btInput = s.getBytes();
            //获得MD5摘要算法的 MessageDigest 对象
            MessageDigest mdInst = MessageDigest.getInstance("MD5");
            //使用指定的字节更新摘要
            mdInst.update(btInput);
            //获得密文
            byte[] md = mdInst.digest();
            char str[] = new char[md.length];
            int k = 0;
            for (int i = 0; i < md.length; i++) {
                byte byte0 = md[i];
                //只取高位
                str[k++] = hexDigits[(byte0 >>> 4 & 0xf) % 10];
            }
            return new String(str);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    public static void main(String[] args) {
        String aa = ConvertNum(DigestUtil.md5Hex("fewfewfeawefawefawefwae"));
//        4252030111208441
        System.out.println(aa);
    }
}
